﻿//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <functional>

#include "Main.h"
#include "OKCANCL2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TFormMain *FormMain;

//---------------------------------------------------------------------------

__fastcall TFormMain::TFormMain(TComponent* Owner)
	: TForm(Owner)
{
	using namespace std::placeholders;
	plFinder = std::make_unique<PLFinderMT>(std::bind(&TFormMain::UICallback, this, _1, _2, _3, _4)); 				//  c++14
//	plFinder = std::make_unique<PLFinderST>(std::bind(&TFormMain::UICallback, this, _1, _2, _3, _4));

//	plFinder->callback = std::bind(&TFormMain::UICallback, this, _1, _2, _3, _4);
//	plFinder->callback = [this](int a, bool b, int c, int d) {  return UICallback(a, b, c, d);  };
}
//---------------------------------------------------------------------------

const char* GamePath 			= "Games";  // 数据目录
const int PLGridDefDots 		= 26;       // 格子大小
const int PLGrid_BorS 			= 20;       // 大小界限
const int PLGridNumColInterval 	= 6; 		// 表头数字列间隔
const int PLGridNumRowInterval 	= -1; 		// 表头数字行间隔
const int PLGridNoPercent 		= 25;    	// 画X时的大小%
const int PLGridYesDots         = 0;        // 画Yes时缩小点数

void __fastcall TFormMain::Button1Click(TObject *Sender)
{
	OpenTextFileDialog1->InitialDir = ExtractFilePath(Application->ExeName) + GamePath;
	if (!OpenTextFileDialog1->Execute()) return;
	Caption = "Picross Luna - " + ChangeFileExt(ExtractFileName(OpenTextFileDialog1->FileName), "");

	if (plFinder->readFromFile(AnsiString(OpenTextFileDialog1->FileName).c_str()))
		MessageDlg("文件有错误！", mtError, TMsgDlgButtons() << mbClose, 0);

	Label1->Caption = "";
	Label2->Caption = "";
	Label3->Caption = "";
	Label4->Caption = "";
	Label5->Caption = "";
	Label6->Caption = "";
	InitGrids();
	Image1->Canvas->Brush->Color = clWhite;
	Image1->Canvas->FillRect(TRect(0, 0, Image1->Width, Image1->Height));

	Button2->Enabled = true;
    Button3->Enabled = true;
}

void TFormMain::InitGrids()
{
	PLGridCharHeight = DrawGrid1->Canvas->TextHeight('0');
	PLGridCharWidth = DrawGrid1->Canvas->TextWidth('0');
	int PLGridColFixDots = plFinder->maxColFlagLen * (PLGridCharHeight + PLGridNumRowInterval);    // 数字列高度
	int PLGridRowFixDots = (plFinder->maxRowFlagLen + 1) * (PLGridCharWidth + PLGridNumColInterval);    // 数字列宽度
	 // 格子大小
	int PLGridDots = plFinder->rows > PLGrid_BorS ? (Height - DrawGrid1->Top - PLGridColFixDots - 60) / plFinder->rows - DrawGrid1->GridLineWidth : PLGridDefDots;
	PLGridNoInterval = PLGridDots * (100 - PLGridNoPercent) / 100 / 2;

	DrawGrid1->Width = plFinder->cols * (PLGridDots + DrawGrid1->GridLineWidth) + PLGridRowFixDots + 5;
	DrawGrid1->Height = plFinder->rows * (PLGridDots + DrawGrid1->GridLineWidth) + PLGridColFixDots + 5;
	DrawGrid1->ColCount = plFinder->cols + 1;
	DrawGrid1->RowCount = plFinder->rows + 1;
	DrawGrid1->LeftCol = 1;
	DrawGrid1->TopRow = 1;

	for (int i = 0; i <= plFinder->cols; ++i)
		DrawGrid1->ColWidths[i] = i == 0 ? PLGridRowFixDots : PLGridDots;
	for (int j = 0; j <= plFinder->rows; ++j)
		DrawGrid1->RowHeights[j] = j == 0 ? PLGridColFixDots : PLGridDots;

	if (DrawGrid1->Left + DrawGrid1->Width > Button1->Left)
		Width = DrawGrid1->Width + 220;

	CurrCol = CurrRow = -1;
	DrawGrid1->Repaint();
}
//---------------------------------------------------------------------------

void TFormMain::DrawAFlag(const Flag& f, int x, int y)
{
    //  已解决的灰色 ，未解决的 黑色（两位数 绿色)
	DrawGrid1->Canvas->Font->Color = f.ok() ? clGray : ( f.n >= 10 ? clGreen : clBlack );
	DrawGrid1->Canvas->TextOut(x, y, f.n);
}



void __fastcall TFormMain::DrawGrid1DrawCell(TObject *Sender, System::LongInt ACol,
		  System::LongInt ARow, TRect &Rect, TGridDrawState State)
{
	int i, x, y, c = ACol - 1, r = ARow - 1;

	// 写每列数字
	if (ARow == 0 && ACol > 0)
	{
		y = Rect.bottom;
		for (i = plFinder->colFlags[c].len - 1; i >= 0; --i)
		{
			x = (Rect.left + Rect.right - DrawGrid1->Canvas->TextWidth(plFinder->colFlags[c].f[i].n)) / 2;
			y -= PLGridCharHeight + PLGridNumRowInterval;
			DrawAFlag(plFinder->colFlags[c].f[i], x, y);
		}
	}

	// 写每行数字
	if (ACol == 0 && ARow > 0)
	{
		x = Rect.right;
		y = (Rect.top + Rect.bottom - PLGridCharHeight) / 2;
		for (i = plFinder->rowFlags[r].len - 1; i >= 0; --i)
		{
			x -= DrawGrid1->Canvas->TextWidth(plFinder->rowFlags[r].f[i].n) + PLGridNumColInterval;
			DrawAFlag(plFinder->rowFlags[r].f[i], x, y);
		}
	}

	// 格子
	if (ACol > 0 && ARow > 0)
		switch (plFinder->map[r][c])
		{
			case Cell::Yes :
				DrawGrid1->Canvas->Brush->Color = clBlack;
				DrawGrid1->Canvas->FillRect(TRect(Rect.left + PLGridYesDots, Rect.top + PLGridYesDots, Rect.right - PLGridYesDots, Rect.bottom - PLGridYesDots));
				break;

			case Cell::No :
				DrawGrid1->Canvas->Brush->Color = clWhite;
				DrawGrid1->Canvas->FillRect(Rect);
				DrawGrid1->Canvas->Pen->Color = clGray;
				DrawGrid1->Canvas->Pen->Width = 2;
				DrawGrid1->Canvas->MoveTo(Rect.left  + PLGridNoInterval, Rect.top    + PLGridNoInterval);
				DrawGrid1->Canvas->LineTo(Rect.right - PLGridNoInterval, Rect.bottom - PLGridNoInterval);
				DrawGrid1->Canvas->MoveTo(Rect.left  + PLGridNoInterval, Rect.bottom - PLGridNoInterval);
				DrawGrid1->Canvas->LineTo(Rect.right - PLGridNoInterval, Rect.top    + PLGridNoInterval);
				break;

			case Cell::Unknow :
				DrawGrid1->Canvas->Brush->Color = clWhite;
				DrawGrid1->Canvas->FillRect(Rect);
		}

	// 每5格的粗线
	if (ACol == DrawGrid1->ColCount - 1 && ARow % 5 == 0)
	{
		DrawGrid1->Canvas->Pen->Width = 1;
		DrawGrid1->Canvas->Pen->Color = clGray;
		DrawGrid1->Canvas->MoveTo(0, Rect.bottom);
		DrawGrid1->Canvas->LineTo(Rect.right + 1, Rect.bottom);
	}

	if (ARow == DrawGrid1->RowCount - 1 && ACol % 5 == 0)
	{
		DrawGrid1->Canvas->Pen->Width = 1;
		DrawGrid1->Canvas->Pen->Color = clGray;
		DrawGrid1->Canvas->MoveTo(Rect.right, 0);
		DrawGrid1->Canvas->LineTo(Rect.right, Rect.bottom + 1);
	}

	// 红框
	if (CurrCol >=0 && CurrCol == c && ARow == DrawGrid1->RowCount - 1)
	{
		DrawGrid1->Canvas->Brush->Color = clRed;
		DrawGrid1->Canvas->FrameRect(TRect(Rect.left - 1, 0, Rect.right + 1, Rect.bottom + 1)) ;
	}

	if (CurrRow >=0 && CurrRow == r && ACol == DrawGrid1->ColCount - 1)
	{
		DrawGrid1->Canvas->Brush->Color = clRed;
		DrawGrid1->Canvas->FrameRect(TRect(0, Rect.top - 1, Rect.right + 1, Rect.bottom + 1)) ;
	}
}
//---------------------------------------------------------------------------

int TFormMain::proc(bool clear)
{
	int res = plFinder->exec(clear, StrToIntDef(LabeledEdit1->Text, 0));
	DrawStep(-1, -1);
	return res;
}

void __fastcall TFormMain::Button2Click(TObject *Sender)
{
	plFinder->needCallback = RadioGroup1->ItemIndex != 2;

	Label3->Caption = "进行中......";
	switch (proc(true))
	{
		case 0 :
			Label3->Font->Color = clBlack;
			Label3->Caption = "搞定！";
			break;
		case 1 :
			Label3->Font->Color = clRed;
			Label3->Caption = "玩儿不转。";
			break;
		case 2 :
			Label3->Font->Color = clRed;
			Label3->Caption = "题目有错误。";
            break;
		case 3 :
			Label3->Font->Color = clBlack;
			Label3->Caption = "用户中断。";
	}

	Label5->Caption = "实际线程数：" + IntToStr(plFinder->threadNum);
}

void __fastcall TFormMain::Button3Click(TObject *Sender)
{
    proc(false);
}
//---------------------------------------------------------------------------

void TFormMain::DrawStep(int col, int row)
{
	String s;
	s.printf(L"%d 步 %.4f 秒", plFinder->findSteps, static_cast<double>(plFinder->timeUsec) / 1000000) ;
	Label1->Caption = s;
	Label2->Caption = "最大递归:" + UIntToStr(plFinder->exhaNum1st);
	Label4->Caption = "第二递归:" + UIntToStr(plFinder->exhaNum2nd);
	Label6->Caption = "合计递归:" + UIntToStr(plFinder->exhaSum);

	CurrCol = col;
	CurrRow = row;
	DrawGrid1->Repaint();

	// 画缩略图
	int ThumbDots = Image1->Width / std::max(plFinder->cols, plFinder->rows);   // 缩略图点数
	int xx = (Image1->Width - plFinder->cols * ThumbDots) / 2;
	int yy = (Image1->Height - plFinder->rows * ThumbDots) / 2;
	Image1->Canvas->Brush->Color = clBlack;
	for (int i = 0; i < plFinder->cols; ++i)
		for (int j = 0; j < plFinder->rows; ++j)
			if (plFinder->map[j][i] == Cell::Yes)
				Image1->Canvas->FillRect(TRect(i * ThumbDots + xx, j * ThumbDots + yy, (i + 1) * ThumbDots + xx, (j + 1) * ThumbDots + yy));
}

//---------------------------------------------------------------------------

// 返回值 0 ：正常  1：用户中断
bool TFormMain::UICallback(int n, bool isCol, int steps, int exhanum)
{
	int col = isCol ? n : -1;
	int row = isCol ? -1 : n;
	DrawStep(col, row);

	if (RadioGroup1->ItemIndex == 0)
		return OKRightDlg->show(col, row, steps, exhanum) != idOK;

	Sleep(StrToInt(Edit1->Text));
	Application->ProcessMessages();
	return 0;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::DrawGrid1SelectCell(TObject *Sender, System::LongInt ACol,
		  System::LongInt ARow, bool &CanSelect)
{
	Cell& cell = plFinder->map[ARow - 1][ACol - 1];
	plFinder->colFlags[ACol - 1].needProc = true;
	plFinder->rowFlags[ARow - 1].needProc = true;
	switch (cell)
	{
		case Cell::Unknow :
			cell = Cell::Yes;
			break;
		case Cell::Yes :
			cell = Cell::No;
			break;
		case Cell::No :
			cell = Cell::Unknow;
	}
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::BitBtn1Click(TObject *Sender)
{
	Close();
}
//---------------------------------------------------------------------------


